﻿//using UnityEngine;
//using UnityEditor;
//using System.IO;
//using System;
//using System.Collections.Generic;

//namespace xres
//{


//    /// <summary>
//    /// 资源热更
//    /// </summary>
//    public class ResUpdateAction : BaseAsyncAction
//    {

//        public const string Err_Download = "Err_Download";

//        string _downloadMode = "";

//        //========== download
//        int _totalDownCount = 0;
//        long _totalDownBytes = 0;
//        long _haveDownBytes = 0;
//        readonly Queue<FileVersion> _toDownloadFiles = new Queue<FileVersion>();
//        readonly List<FileVersion> _hasDownloadFiles = new List<FileVersion>();
//        readonly List<FileVersion> _downloadFailFiles = new List<FileVersion>();

//        /// <summary>
//        /// 正在执行的download
//        /// </summary>
//        readonly List<DownloadFileAction> _inDownloadActionList = new List<DownloadFileAction>();
//        readonly Queue<DownloadFileAction> _idleDownloadActionQueue = new Queue<DownloadFileAction>();
//        //==========


//        //========== copy

//        int _totalCopyCount = 0;
//        readonly Queue<FileVersion> _toCopyFiles = new Queue<FileVersion>();
//        readonly List<FileVersion> _hasCopyFiles = new List<FileVersion>();
//        readonly List<FileVersion> _copyFailFiles = new List<FileVersion>();

//        readonly List<CopyFileAction> _inCopyActionList = new List<CopyFileAction>();
//        readonly Queue<CopyFileAction> _idleCopyActionQueue = new Queue<CopyFileAction>();
//        //==========


//        public float CheckProgress()
//        {
//            switch (_state)
//            {
//            case BaseLoaderState.Init:
//                return 0;

//            case "Check":
//                return 0.01f;

//            case "DownloadFiles":
//            {
//                var inDownBytes = 0f;
//                for (var i = 0; i < _inDownloadActionList.Count; ++i)
//                {
//                    inDownBytes += _inDownloadActionList[i].CheckDownBytes();
//                }
//                float prg = 0.98f * (inDownBytes + _haveDownBytes) / _totalDownBytes;
//                return 0.01f + prg;
//            }

//            case "ReplaceOldFiles":
//                return 0.99f;

//            }

//            return 1;
//        }

//        public void ResUpdate()
//        {
//            switch (_state)
//            {
//            case BaseLoaderState.Init:
//            case BaseLoaderState.Finish:
//                break;

//            default:
//                return;
//            }

//            _state = "Check";

//            var sb = ResPath.TempStringBuilder;
//            var externalPath = ResPath.BuildExternalBundlePath(sb, "Versions.bin");
//            if (File.Exists(externalPath))
//            {
//                Debug.Log($"ResUpdate: Versions eixst");
//                try
//                {
//                    _externalVersions = Versions.CreateFromFile(externalPath);

//                    //请求服务器的ResVer.bin
//                    var action = new GetTextAction();
//                    action.GetText("http://localhost:8081/Windows/ResVer.bin");
//                    action.onComplete = OnComplete_ServerResVer;
//                }
//                catch (Exception ex) //文件读取失败
//                {
//                    Debug.LogError($"msg: {ex.Message}, st: {ex.StackTrace}");

//                    SetError(Err_Load_External_Versions, $"external Versions file load fail");
//                    SetFinishAndNotify(ErrMsg);
//                    return;
//                }
//            }
//            else
//            {
//                Debug.Log($"ResUpdate: Versions not eixst");
//                //直接请求服务器的Versions.bin
//                RequestServerVersions();
//            }
//        }

//        void OnComplete_ServerResVer(object obj, string type, object data)
//        {
//            var action = (GetTextAction)obj;
//            if (!string.IsNullOrEmpty(action.ErrType))
//            {
//                SetError(Err_Server_ResVer, action.ErrMsg);
//                Debug.LogError(ErrMsg);
//                SetFinishAndNotify(ErrMsg);
//                return;
//            }

//            try
//            {
//                var serverResVer = int.Parse(action.Text);
//                if (serverResVer <= _externalVersions.resVersion)
//                {
//                    Debug.Log($"ResVer: server: {serverResVer}, local: {_externalVersions.resVersion}");
//                    VerifyLocalFiles();
//                    return;
//                }
//            }
//            catch (Exception ex)
//            {
//                SetError(Err_Server_ResVer, $"server ResVer parse fail");
//                Debug.LogError(ErrMsg);
//                SetFinishAndNotify(ErrMsg);
//                return;
//            }

//            RequestServerVersions();
//        }

//        void VerifyLocalFiles()
//        {
//            var sb = ResPath.TempStringBuilder;

//            _totalDownBytes = 0;
//            _haveDownBytes = 0;
//            var externalFiles = _externalVersions.files;
//            foreach (var entry in externalFiles)
//            {
//                var fv = entry.Value;
//                var filePath = ResPath.BuildExternalBundlePath(sb, fv.path);
//                if (!File.Exists(filePath))
//                {
//                    Debug.Log($"VerifyLocalFiles: file not exists: {fv.path}");
//                    _toDownloadFiles.Enqueue(fv);
//                    _totalDownBytes += fv.len;
//                    continue;
//                }

//                var fi = new FileInfo(filePath);
//                if (fv.len != fi.Length)
//                {
//                    Debug.Log($"VerifyLocalFiles: file length not match: {fv.path}");
//                    _toDownloadFiles.Enqueue(fv);
//                    _totalDownBytes += fv.len;
//                    continue;
//                }
//            }

//            _totalDownCount = _toDownloadFiles.Count;
//            if (_totalDownCount > 0)
//            {
//                var alert = AlertLayer.Obtain();
//                alert.Open("", "发现资源更新, 是否更新", null);

//                _downloadMode = "DownloadVerifyFailFiles";
//                _state = "DownloadFiles";
//                CheckToDownFile();
//            }
//            else
//            {
//                Debug.Log($"ResUpdate: verify ok, no need update");
//                SetError("", "");
//                SetFinishAndNotify("");
//            }
//        }

//        void RequestServerVersions()
//        {
//            //请求服务器的 Versions.bin
//            var action = new GetTextAction();
//            action.GetText("http://localhost:8081/Windows/Versions.bin");
//            action.onComplete = OnComplete_ServerVersions;
//        }

//        void OnComplete_ServerVersions(object obj, string type, object data)
//        {
//            var action = (GetTextAction)obj;
//            if (!string.IsNullOrEmpty(action.ErrType))
//            {
//                SetError(Err_Server_Versions, action.ErrMsg);
//                Debug.LogError(ErrMsg);
//                SetFinishAndNotify(ErrMsg);
//                return;
//            }

//            _serverVersions = null;
//            Versions serverVersions;
//            try
//            {
//                serverVersions = Versions.CreateFromString(action.Text);
//                _serverVersions = serverVersions;
//            }
//            catch (Exception ex)
//            {
//                Debug.LogError($"msg: {ex.Message}, st: {ex.StackTrace}");

//                SetError(Err_Server_Versions, $"server Versions parse fail");
//                SetFinishAndNotify(ErrMsg);
//                return;
//            }

//            _totalDownBytes = 0;
//            _haveDownBytes = 0;
//            if (null == _externalVersions) //完整下载
//            {
//                Debug.Log($"ResUpdate: full download");

//                foreach (var entry in serverVersions.files)
//                {
//                    var fv = entry.Value;
//                    _toDownloadFiles.Enqueue(fv);
//                    _totalDownBytes += fv.len;
//                }
//            }
//            else
//            {
//                Debug.Log($"ResUpdate: download some");

//                var externalFiles = _externalVersions.files;
//                var serverFiles = serverVersions.files;
//                foreach (var entry in serverFiles)
//                {
//                    var serverFv = entry.Value;

//                    if (externalFiles.TryGetValue(entry.Key, out var externalFv))
//                    {
//                        if (serverFv.crc != externalFv.crc) //发生变动
//                        {
//                            _toDownloadFiles.Enqueue(serverFv);
//                            _totalDownBytes += serverFv.len;
//                        }

//                        externalFiles.Remove(entry.Key);
//                    }
//                    else //本地没有
//                    {
//                        _toDownloadFiles.Enqueue(serverFv);
//                        _totalDownBytes += serverFv.len;
//                    }
//                }
//            }

//            _totalDownCount = _toDownloadFiles.Count;
//            _state = "DownloadFiles";
//            CheckToDownFile();
//        }

//        /// <summary>
//        /// 继续把下载失败的下载完
//        /// </summary>
//        public void ReDownloadFailFiles()
//        {
//            if (BaseLoaderState.Finish != _state)
//                return;

//            if (_downloadFailFiles.Count <= 0)
//                return;


//            for (var i = 0; i < _downloadFailFiles.Count; ++i)
//            {
//                _toDownloadFiles.Enqueue(_downloadFailFiles[i]);
//            }
//            _downloadFailFiles.Clear();

//            _state = "DownloadFiles";
//            CheckToDownFile();
//        }

//        void CheckToDownFile()
//        {
//            if (_toDownloadFiles.Count <= 0 && _inDownloadActionList.Count <= 0) //所有都copy完了
//            {
//                if (_downloadFailFiles.Count > 0)
//                {
//                    SetError(Err_Download, $"some files download fail: {_downloadFailFiles.Count}");
//                    Debug.LogError(ErrMsg);
//                    SetFinishAndNotify(ErrMsg);
//                    //提示: 下载失败, 是否重试
//                    /*
//                    for (var i = 0; i < _downloadFailFiles.Count; ++i)
//                    {
//                        _toDownloadFiles.Enqueue(_downloadFailFiles[i]);
//                    }
//                    _downloadFailFiles.Clear();
//                    */
//                }
//                else
//                {
//                    ReplaceOldFiles();
//                }
//                return;
//            }

//            var sb = ResPath.TempStringBuilder;
//            var diff = 5 - _inDownloadActionList.Count; //最多5个同时进行
//            for (var i = 0; i < diff && _toDownloadFiles.Count > 0; ++i)
//            {
//                var fv = _toDownloadFiles.Dequeue();

//                DownloadFileAction downloadAction;
//                if (_idleDownloadActionQueue.Count > 0)
//                    downloadAction = _idleDownloadActionQueue.Dequeue();
//                else
//                    downloadAction = new DownloadFileAction();

//                var url = sb.Append("http://localhost:8081/Windows/").Append(fv.path).ToString();
//                sb.Clear();

//                downloadAction.UserData = fv;
//                downloadAction.onComplete = OnComplete_DownloadOneFile;
//                downloadAction.Download(url, ResPath.BuildExternalTempBundlePath(ResPath.TempStringBuilder, fv.path), true); //下载到临时目录
//                _inDownloadActionList.Add(downloadAction);
//            }

//            if (false) Debug.Log($"CheckToDownFile: toDown: {_toDownloadFiles.Count}, inDown: {_inDownloadActionList.Count}");
//        }

//        void OnComplete_DownloadOneFile(object obj, string type, object userData)
//        {
//            var downloadAction = (DownloadFileAction)obj;

//            if (_idleDownloadActionQueue.Count < 5) //最多5个
//                _idleDownloadActionQueue.Enqueue(downloadAction);
//            _inDownloadActionList.Remove(downloadAction);


//            var fv = (FileVersion)userData;

//            if (!string.IsNullOrEmpty(downloadAction.ErrType)) //下载出错
//            {
//                _downloadFailFiles.Add(fv);
//            }
//            else
//            {
//                _hasDownloadFiles.Add(fv);
//                _haveDownBytes += fv.len;
//            }

//            if (true) Debug.Log($"OnComplete_DownloadOneFile: inDown: {_inDownloadActionList.Count}, hasDown: {_hasDownloadFiles.Count}, toDown: {_toDownloadFiles.Count}");

//            CheckToDownFile();
//        }

//        //新下载文件覆盖旧文件
//        void ReplaceOldFiles()
//        {
//            if (true) Debug.Log($"ReplaceOldFiles");

//            _state = "ReplaceOldFiles";

//            for (var i = 0; i < _hasDownloadFiles.Count; ++i)
//            {
//                _toCopyFiles.Enqueue(_hasDownloadFiles[i]);
//            }
//            _hasDownloadFiles.Clear();

//            CheckToCopyFile();
//        }

//        //多个文件同时异步copy
//        void CheckToCopyFile()
//        {
//            if (true) Debug.Log($"CheckToCopyFile: toCopy: {_toCopyFiles.Count}, inCopy: {_inCopyActionList.Count}");

//            if (_toCopyFiles.Count <= 0 && _inCopyActionList.Count <= 0) //所有都copy完了
//            {
//                SaveVersions();
//                return;
//            }

//            var diff = 5 - _inCopyActionList.Count; //最多5个同时进行
//            for (var i = 0; i < diff && _toCopyFiles.Count > 0; ++i)
//            {
//                var fv = _toCopyFiles.Dequeue();

//                CopyFileAction copyAction;
//                if (_idleCopyActionQueue.Count > 0)
//                    copyAction = _idleCopyActionQueue.Dequeue();
//                else
//                    copyAction = new CopyFileAction();

//                var sb = ResPath.TempStringBuilder;
//                var srcPath = ResPath.BuildExternalTempBundlePath(sb, fv.path);
//                var dstPath = ResPath.BuildExternalBundlePath(sb, fv.path);

//                copyAction.Copy(srcPath, dstPath, true);
//                copyAction.UserData = fv;
//                copyAction.onComplete = OnComplete_CopyOneFile;
//                _inCopyActionList.Add(copyAction);
//            }
//        }

//        void OnComplete_CopyOneFile(object obj, string type, object userData)
//        {
//            if (true) Debug.Log($"OnComplete_CopyOneFile:");

//            var copyAction = (CopyFileAction)obj;

//            if (_idleCopyActionQueue.Count < 5) //最多5个
//                _idleCopyActionQueue.Enqueue(copyAction);
//            _inCopyActionList.Remove(copyAction);

//            _hasCopyFiles.Add((FileVersion)userData);

//            if (false) Debug.Log($"OnComplete_CopyOneFile: inCopy: {_inCopyActionList.Count}, hasCopy: {_hasCopyFiles.Count}");

//            if (!string.IsNullOrEmpty(copyAction.ErrMsg))
//            {
//                //copy出错
//            }

//            CheckToCopyFile();
//        }


//        void SaveVersions()
//        {
//            if (true) Debug.Log($"SaveVersions");

//            if ("" != _downloadMode)
//            {
//                Debug.Log($"ResUpdate: update finish 1");
//                SetError("", "");
//                SetFinishAndNotify("");
//                return;
//            }

//            var sb = ResPath.TempStringBuilder;
//            Versions.WriteOut(_serverVersions, ResPath.BuildExternalBundlePath(sb, "Versions.bin"), sb);

//            //服务器已经删除的
//            var externalFiles = _externalVersions.files;
//            Debug.Log($"server has delete: {externalFiles.Count}");
//            foreach (var entry in externalFiles)
//            {
//                var fv = entry.Value;
//                var bundleFilePath = ResPath.BuildExternalBundlePath(sb, fv.path);
//                if (File.Exists(bundleFilePath))
//                {
//                    Debug.Log($"server has delete: {fv.path}");
//                    File.Delete(bundleFilePath);
//                }
//            }

//            Debug.Log($"ResUpdate: update finish 2");
//            SetError("", "");
//            SetFinishAndNotify("");
//        }

//    } //end of class


//}

